﻿using Newtonsoft.Json;
using PW.Api.Model;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace PW.Api
{
    public class Request
    {
        public static RestClient restclient = new RestClient("http://localhost:8888");
        public static string token = null;
        public static int timeout = 10000;
        public static ResponseContent post(string url, Object data, Object queryParams = null)
        {
            var request = getRequest(url, Method.POST, queryParams, data);
            IRestResponse response = restclient.Execute(request);
            ResponseContent res = deserializeResponseContent(response);
            return res;
        }

        public static ResponseContent put(string url, Object data, Object queryParams = null)
        {
            var request = getRequest(url, Method.PUT, queryParams, data);
            IRestResponse response = restclient.Execute(request);
            ResponseContent res = deserializeResponseContent(response);
            return res;
        }

        public static ResponseContent delete(string url, Object data, Object queryParams = null)
        {
            var request = getRequest(url, Method.DELETE, queryParams, data);
            IRestResponse response = restclient.Execute(request);
            ResponseContent res = deserializeResponseContent(response);
            return res;
        }

        public static ResponseContent get(string url, Object queryParams, Object data = null)
        {

            var request = getRequest(url, Method.GET, queryParams, data);
            IRestResponse response = restclient.Execute(request);
            ResponseContent res = deserializeResponseContent(response);
            return res;
        }

        public static async Task<ResponseContent> postAsync(string url, Object data, Object queryParams = null)
        {
            var request = getRequest(url, Method.POST, queryParams, data);
            IRestResponse response = await restclient.ExecutePostAsync(request);
            ResponseContent res = deserializeResponseContent(response);
            return res;
        }

        public static async Task<ResponseContent> getAsync(string url, Object queryParams, Object data = null)
        {

            var request = getRequest(url, Method.GET, queryParams, data);
            IRestResponse response = await restclient.ExecuteGetAsync(request);
            ResponseContent res = deserializeResponseContent(response);
            return res;
        }

        static ResponseContent deserializeResponseContent(IRestResponse response) {
            ResponseContent res = JsonConvert.DeserializeObject<ResponseContent>(response.Content);
            if (res == null)
            {
                res = new ResponseContent();
                res.response = response;
            }
            return res;
        }

        static RestRequest getRequest(string url, Method method, Object queryParams, Object data) {
            RestRequest request = new RestRequest(url, method);
            request.AddHeader("Content-Type", "application/json");
            request.Timeout = timeout;
            request.AddHeader("Cache-Control", "no-cache");
            if (queryParams != null) {
                List<Parameter> _queryParams = toParameters(queryParams);
                if (_queryParams != null && _queryParams.Count > 0) {
                    request.AddOrUpdateParameters(_queryParams);
                }
            }
           
            if (data != null)
            {
                request.AddParameter("application/json; charset=utf-8", JsonConvert.SerializeObject(data), ParameterType.RequestBody);
            }
            return request;
        }

        static List<Parameter> toParameters(Object obj) {
            List<Parameter> list = new List<Parameter>();
            if (obj is List<Parameter>)
            {
                list = obj as List<Parameter>;
            }
            Type t = obj.GetType();
            PropertyInfo[] pi = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (PropertyInfo p in pi)
            {
                MethodInfo mi = p.GetGetMethod();
                if (mi != null && mi.IsPublic)
                {
                    Object value = mi.Invoke(obj, new Object[] { });
                    if (value != null) {
                        list.Add(new Parameter(p.Name, value, ParameterType.GetOrPost));
                    }
                }
            }
            return list;
        }
    }
}
